package com.zhou.system.management.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.zhou.common.lib.util.BeanUtil;
import com.zhou.system.management.constant.UserContext;
import com.zhou.system.management.entity.SysMenu;
import com.zhou.system.management.mapper.SysMenuMapper;
import com.zhou.system.management.model.vo.RouteVo;
import com.zhou.system.management.model.vo.SysMenuAddVo;
import com.zhou.system.management.model.vo.SysMenuTreeVo;
import com.zhou.system.management.model.vo.SysMenuUpdateVo;
import com.zhou.system.management.security.model.MyUserDetails;
import com.zhou.system.management.service.ISysMenuService;
import com.zhou.system.management.util.UserUtil;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 系统菜单表 服务实现类
 * </p>
 *
 * @author zxf
 * @since 2023-05-18
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Override
    public List<RouteVo> queryMenuRoute() {
        MyUserDetails myUserDetails = UserContext.currentUser();
        Long userId = myUserDetails.getUserId();
        List<SysMenu> sysMenus = null;
        if (UserUtil.isAdmin(userId)) {
            LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.<SysMenu>lambdaQuery()
                    .eq(SysMenu::getVisible, 0)
                    .eq(SysMenu::getStatus, 0)
                    .orderByAsc(SysMenu::getOrderNum)
                    .orderByAsc(SysMenu::getMenuId);
            sysMenus = list(queryWrapper);
        } else {
            sysMenus = baseMapper.queryMenus(userId, myUserDetails.getCurrOrgId());
        }
        List<RouteVo> result = Lists.newArrayList();
        if (sysMenus.size() > 0) {
            result = buildRoute(sysMenus, 0L);
        }
        return result;
    }

    @Override
    public List<SysMenuTreeVo> queryMenuTree() {
        List<SysMenu> list = list();
        return buildTree(list, 0L);
    }

    @Override
    public void add(SysMenuAddVo addVo) {
        SysMenu sysMenu = BeanUtil.copyObject(addVo, SysMenu.class);
        save(sysMenu);
    }

    @Override
    public void update(SysMenuUpdateVo updateVo) {
        SysMenu sysMenu = BeanUtil.copyObject(updateVo, SysMenu.class);
        updateById(sysMenu);
    }


    private List<SysMenuTreeVo> buildTree(List<SysMenu> list, Long parentId) {
        Map<Long, SysMenuTreeVo> orgMap = new HashMap<>(128);
        list.forEach(menu -> {
            Long pid = menu.getParentId();
            Long oid = menu.getMenuId();

            // 处理当前组织
            SysMenuTreeVo current = orgMap.computeIfAbsent(oid, (id) -> new SysMenuTreeVo());
            copyProperties(menu, current);

            // 处理父组织 绑定父级组织
            if (!parentId.equals(oid)) {
                SysMenuTreeVo parent = orgMap.computeIfAbsent(pid, (id) -> new SysMenuTreeVo());
                parent.addChild(current);
            }
        });
        SysMenuTreeVo root = orgMap.get(parentId);
        return root.getChild();
    }

    private List<RouteVo> buildRoute(List<SysMenu> list, Long parentId) {
        Map<Long, RouteVo> orgMap = new HashMap<>(128);
        list.forEach(menu -> {
            Long pid = menu.getParentId();
            Long oid = menu.getMenuId();

            // 处理当前组织
            RouteVo current = orgMap.computeIfAbsent(oid, (id) -> new RouteVo());
            copyProperties(menu, current);

            // 处理父组织 绑定父级组织
            if (!parentId.equals(oid)) {
                RouteVo parent = orgMap.computeIfAbsent(pid, (id) -> new RouteVo());
                parent.addChild(current);
            }
        });
        RouteVo root = orgMap.get(parentId);
        return root.getChild();
    }

    private void copyProperties(SysMenu origin, RouteVo target) {
        target.setTitle(origin.getMenuName());
        target.setIcon(origin.getMenuIcon());
        target.setHref(origin.getPath());
        target.setTarget(origin.getOpenType() == 0 ? "_self" : "_blank");
    }

    private void copyProperties(SysMenu origin, SysMenuTreeVo target) {
        target.setTitle(origin.getMenuName());
        target.setIcon(origin.getMenuIcon());
        target.setId(origin.getMenuId());
    }
}
